;;; the control panel displays a control panel on top of its children

(defpackage :panel
  (:use :cl)
  (:export :control-panel))

(in-package :panel)

(defun get-visibility-option ()
  (print `("panel visibility" ,(exp:get-option-value exp:*experiment* :control-panel)))
  (eq (exp:get-option-value exp:*experiment* :control-panel)
      :no-control-panel))

(defclass control-panel (exp:subsequence)
  ((panel :initform nil :accessor panel)
   (invisiblep :initform (get-visibility-option) :initarg :invisiblep :accessor invisiblep)
   (extra :initform nil :initarg :extra :accessor extra)))

(defmethod exp:state-init (exp (state control-panel))
  (macrolet ((dispatch (source)
               `(exp:dispatch-event-fn exp (exp::current-state exp) exp:click-event :source ,source))
             (callback (&body body)
                       `(lambda (b)
                          (declare (ignore b))
                          ,@body)))
    (exp:lg 'start :index (exp:subsequence-index state))
    (with-slots (panel invisiblep extra) state
      (unless invisiblep
        (let ((height (+ 190 (* 30 (length extra)))))
          (gwee:with-layout
              (:views
               (undo gwee:button :data "Undo" :click-callback (dispatch :undo))
               (step gwee:button :data "Step" :click-callback (dispatch :step))
               (next-problem gwee:button :data "Prb>"
                                         :click-callback (callback
                                                             (gwee:cancel-all-timers)
                                                             (exp:lg 'panel-next-problem)
                                                             (signal 'exp::forward)))
               (prev-problem gwee:button :data "<Prb"
                                         :click-callback (callback
                                                             (gwee:cancel-all-timers)
                                                             (exp:lg 'panel-previous-problem)
                                                             (signal 'exp::backward)))
               (prev-block gwee:button :data "<Blk"
                                       :click-callback (callback
                                                           (gwee:cancel-all-timers)
                                                           (exp:lg 'panel-previous-block)
                                                           (exp::jump-to exp 'exp:block-start t)))
               (next-block gwee:button :data "Blk>"
                                       :click-callback (callback
                                                           (gwee:cancel-all-timers)
                                                           (exp:lg 'panel-next-block)
                                                           (exp::jump-to exp 'exp:block-start)))
               (hide gwee:button :data "Hide Panel"
                                 :click-callback (callback
                                                     (gwee:delete-view panel)))
               (main-menu gwee:button :data "Main Menu" :click-callback (callback (throw 'exp::restart nil))))
              (:layouts
               (panel-view gwee::drawer-view
                           (top)
                           :title "Control Panel"
                           :x 0
                           :y :bottom
                           :width 150
                           :height 20
                           :drawer-size height)
               (top gwee:column-layout
                    (walk problems blocks hide main-menu)
                    :background (gwee:gray 200)
                    :y 20
                    :padding 10
                    :width 150
                    :height (- height 20))
               (problems gwee:row-layout
                         (prev-problem next-problem)
                         :name :problems
                         :background (gwee:gray 200)
                         :padding 5
                         :height :minimum)
               (blocks gwee:row-layout
                       (prev-block next-block)
                       :name :blocks
                       :background (gwee:gray 200)
                       :padding 5
                       :height :minimum)
               (walk gwee:row-layout
                     (undo step)
                     :name :walk
                     :background (gwee:gray 200)
                     :padding 5
                     :height :minimum))
              (:parent gwee:*top-view*
               :delete-p nil)
            (print (gwee:view-parent top))
            (dolist (i extra)
              (make-instance 'gwee:button
                             :parent top
                             :data i
                             :format-function (lambda (d) (substitute #\Space #\- (string-capitalize d)))
                             :click-callback (lambda (b) (funcall (gwee:view-data b)))))
            (setf panel panel-view)))))))

(defmethod exp:state-clean-up progn (exp (state control-panel))
  (declare (ignore exp))
  (unless (invisiblep state)
    (gwee:delete-view (panel state))))

(defmethod exp:state-dump append (exp (state control-panel))
  (declare (ignore exp))
  `(:extra ,(extra state)
    :invisiblep ,(invisiblep state)))
